from starlette.endpoints import HTTPEndpoint
from starlette.responses import JSONResponse
from database import Session
import config
from sqlalchemy.exc import DBAPIError
from dao import DaoCompanyOperator
from model.ModCompanyOperator import CompanyOperator
import requests
from redis_connection import redis_conn as redis
from wxenterprise.DepartmentVsBureau import calculate_department_level


def find_max_priority_department(departments, belongs):
    mapped_belongs = [dep for dep in departments if dep["id"] in belongs]
    index = -1
    for i, v in enumerate(mapped_belongs):
        if index == -1 or v["level"] < mapped_belongs[index]["level"]:
            index = i
    if index == -1:
        return None
    else:
        return mapped_belongs[index]["id"]


class SetupCompanyOperator(HTTPEndpoint):

    async def get(self, request):
        session = Session()
        try:
            openid = request.path_params["openid"]
            return DaoCompanyOperator.get_operator_info(session, openid)
        finally:
            session.close()

    async def put(self, request):
        session = Session()
        try:
            openid = request.path_params["openid"]
            operator = session.query(CompanyOperator).filter(CompanyOperator.openid == openid).one_or_none()
            if operator is None:
                raise ValueError()
            update_data = await request.json()
            operator.audit_permission = update_data['audit']
            operator.company_employee = update_data['local']
            session.commit()

            return JSONResponse({"result": "1"})
        except (DBAPIError, ValueError):
            session.rollback()
            return JSONResponse({"result": "0"})
        finally:
            session.close()


class CompanyOperatorControl(HTTPEndpoint):
    async def get(self, request):
        session = Session()
        try:
            return JSONResponse(DaoCompanyOperator.get_all_operators(session))
        finally:
            session.close()

    async def post(self, request):
        session = Session()
        try:
            token = redis.hget(config.ENT_ACCESS_TOKEN, "token")
            person_respone = requests.get("https://qyapi.weixin.qq.com/cgi-bin/user/list",
                                          params={
                                              "access_token": token,
                                              "department_id": 1,
                                              "fetch_child": 1
                                          })
            person_respone.raise_for_status()
            dep_respone = requests.get("https://qyapi.weixin.qq.com/cgi-bin/department/list",
                                       params={
                                           "access_token": token
                                       })
            dep_respone.raise_for_status()
            person_data = person_respone.json()
            dep_data = dep_respone.json()
            if "errcode" in dep_data and dep_data["errcode"] == 0:
                departments = dep_data["department"]
                for department in departments:
                    department["level"] = calculate_department_level(departments, department["id"])
            else:
                raise ValueError()

            if "errcode" in person_data and person_data["errcode"] == 0:
                maintained_persons = session.query(CompanyOperator).all()
                persons = person_data["userlist"]
                for person in persons:
                    if not any([mp.openid == person["userid"] for mp in maintained_persons]):
                        belongs = find_max_priority_department(departments, person["department"])
                        dept = next(filter(lambda d: d["id"] == belongs, departments))
                        belong_index = person["department"].index(belongs)
                        new_person = CompanyOperator()
                        new_person.openid = person["userid"]
                        new_person.name = person["name"]
                        new_person.audit_permission = "1" if person["is_leader_in_dept"][belong_index] == 1 else "0"
                        new_person.departmentid = belongs if belongs is not None else "1"
                        new_person.company_employee = "1" if dept["level"] < 3 else "0"
                        session.add(new_person)
                    else:
                        belongs = find_max_priority_department(departments, person["department"])
                        dept = next(filter(lambda d: d["id"] == belongs, departments))
                        belong_index = person["department"].index(belongs)
                        m_person = next(filter(lambda p: p.openid == person["userid"], maintained_persons))
                        m_person.audit_permission = "1" if person["is_leader_in_dept"][belong_index] == 1 else "0"
                        m_person.departmentid = belongs if belongs is not None else "1"
                        m_person.company_employee = "1" if dept["level"] < 3 else "0"
            else:
                raise ValueError()

            session.commit()
            return JSONResponse({"result": "1"})
        except (requests.HTTPError, ValueError):
            session.rollback()
            return JSONResponse({"result": "0"})
        finally:
            session.close()
